home *** CD-ROM | disk | FTP | other *** search
/ Mac Power 1996 June / MACPOWER-1996-06.ISO.7z / MACPOWER-1996-06.ISO / Apple関連 / OpenDoc J-1.0 / 3rd Party Components / Attachmate CyberTerm / TurboTCP 2.0.1 / Terminal pane / CTerminalPane.cp next >
Text File  |  1995-12-05  |  16KB  |  730 lines

  1. /*
  2. ** CTerminalPane.cp
  3. **
  4. **    TerminalPane library
  5. **    Terminal display pane
  6. **
  7. **    Copyright ゥ 1993ミ94, FrostByte Design / Eric Scouten
  8. **
  9. */
  10. #if 0
  11.  
  12. #include "CTerminalPane.h"
  13.  
  14. #include <Events.h>
  15. #include "CBureaucrat.h"
  16. #include "CScrollPane.h"
  17. #include "Global.h"
  18. #include "LongCoordinates.h"
  19. #include "LongQD.h"
  20.  
  21.  
  22.  
  23. extern CBureaucrat* gGopher;
  24.  
  25.  
  26. #define resetInvalsChar 3
  27.  
  28. TCL_DEFINE_CLASS_D1(CTerminalPane, CPanorama)
  29.  
  30.  
  31. //    ムム constructor ムム
  32.  
  33. /*______________________________________________________________________
  34. **
  35. ** constructors
  36. **
  37. **    Initialize the pane. Nothing special here. Parameters and usage are all the same
  38. **    as for CPanorama.
  39. **
  40. */
  41.  
  42. CTerminalPane::CTerminalPane() : CPanorama()
  43.     { CTerminalPaneX(); }
  44.  
  45. CTerminalPane::CTerminalPane(CView* anEnclosure, CBureaucrat* aSupervisor,
  46.                         short aWidth, short aHeight, short aHEncl, short aVEncl,
  47.                         SizingOption aHSizing, SizingOption aVSizing)
  48.     : CPanorama(anEnclosure, aSupervisor, aWidth, aHeight, aHEncl, aVEncl, aHSizing, aVSizing)
  49.     { CTerminalPaneX(); }
  50.  
  51. void CTerminalPane::ITerminalPane(CView* anEnclosure, CBureaucrat* aSupervisor,
  52.                         short aWidth, short aHeight, short aHEncl, short aVEncl,
  53.                         SizingOption aHSizing, SizingOption aVSizing)
  54. {
  55.     CPanorama::IPanorama(anEnclosure, aSupervisor, aWidth, aHeight, aHEncl, aVEncl, aHSizing, aVSizing);
  56.     if (member(itsEnclosure, CScrollPane))
  57.         ((CScrollPane*) itsEnclosure)->SetSteps(pixelsX, pixelsY);
  58. }
  59.  
  60.  
  61. /*______________________________________________________________________
  62. **
  63. ** CTerminalPaneX (private method)
  64. **
  65. **    Finish initialization for terminal pane.
  66. **
  67. */
  68.  
  69. void CTerminalPane::CTerminalPaneX()
  70.  
  71. {
  72.     LongRect theBounds;
  73.  
  74.     SetLongRect(&theBounds, 0, 0, sizeX, sizeY);
  75.     SetBounds(&theBounds);
  76.     SetCanBeGopher(TRUE);
  77.     SetWantsClicks(TRUE);
  78.     
  79.     if (member(itsEnclosure, CScrollPane))
  80.         ((CScrollPane*) itsEnclosure)->SetSteps(pixelsX, pixelsY);
  81.     
  82.     charsToInvalLine = resetInvalsChar;
  83.     blinkCursor = FALSE;
  84.     cursorVis = TRUE;
  85.     lastCursorCol = lastCursorLine = 0;
  86.     lastCursorTick = 0L;
  87.     disableKeyScroll = FALSE;
  88.     DoClearScreen();
  89. }
  90.  
  91.  
  92. //    ムム drawing  ムム
  93.  
  94. /*______________________________________________________________________
  95. **
  96. ** Draw
  97. **
  98. **    Draw characters from the theScreen array onto the real screen.
  99. **
  100. **        area (Rect*):    area to be redrawn (in frame coordinates)
  101. **
  102. */
  103.  
  104. void CTerminalPane::Draw(Rect* area)
  105.  
  106. {
  107.     short    left, top, right, bottom;        // char coordinatates of draw region
  108.     short    dLine;                    // where to draw now
  109.     LongRect    theLongArea;                // frame coordinates of region
  110.     LongPt    theLongPt;
  111.     Point        thePoint;
  112.  
  113.  
  114.     // figure draw region
  115.  
  116.     charsToInvalLine = resetInvalsChar;
  117.     QDToFrameR(area, &theLongArea);
  118.     left = (theLongArea.left - offsetX) / pixelsX;
  119.     right = (theLongArea.right -offsetX + 1) / pixelsX;
  120.     top = (theLongArea.top - offsetY) / pixelsY;
  121.     bottom = (theLongArea.bottom -offsetY + 1) / pixelsY;
  122.  
  123.  
  124.     // do range checking
  125.  
  126.     left = TCLMax(left, 0);
  127.     top = TCLMax(top, 0);
  128.     right = TCLMin(right, maxX-1);
  129.     bottom = TCLMin(bottom, maxY-1);
  130.  
  131.  
  132.     // hard-wire for Monaco 9: Mom, donユt look at this code!
  133.  
  134.     TextFont(4);
  135.     TextFace(0);
  136.     TextSize(9);
  137.  
  138.  
  139.     // draw the stuff
  140.  
  141.     if (left <= right) {
  142.         dLine = top;
  143.         while (dLine <= bottom) {
  144.             SetLongPt(&theLongPt, left * pixelsX, dLine * pixelsY);
  145.             FrameToQD(&theLongPt, &thePoint);
  146.             MoveTo(thePoint.h + offsetX, thePoint.v + offsetY + pixelsY-2);
  147.             DrawText(&theScreen[dLine][left], 0, right-left+1);
  148.             dLine++;
  149.         }
  150.     }
  151.  
  152.  
  153.     // check to see if we overwrote the cursor
  154.  
  155.     if ((left <= theColumn) && (right >= theColumn) &&
  156.      (top <= theLine) && (bottom >= theLine) && cursorVis)
  157.          InvertCursor(theColumn, theLine);
  158.     
  159. }
  160.  
  161.  
  162. //    ムム blinking cursor support ムム
  163.  
  164. /*______________________________________________________________________
  165. **
  166. ** Dawdle
  167. **
  168. **    Blink the cursor if necessary. Cursor blinks at the user-defined rate for insertion point
  169. **    blinking.
  170. **
  171. **        maxSleep (long*):    maximum sleep value, updated if necessary
  172. **
  173. */
  174.  
  175. void CTerminalPane::Dawdle(long* maxSleep)
  176.  
  177. {
  178.     CPanorama::Dawdle(maxSleep);
  179.     if (blinkCursor) {
  180.         *maxSleep = TCLMin(*maxSleep, GetCaretTime());
  181.         if (LMGetTicks() >= lastCursorTick + GetCaretTime()) {
  182.             cursorVis = !cursorVis;
  183.             lastCursorTick = LMGetTicks();
  184.             InvalCharRect(theColumn, theLine, theColumn, theLine);
  185.         }
  186.     }
  187. }
  188.  
  189.  
  190. /*______________________________________________________________________
  191. **
  192. ** BecomeGopher
  193. **
  194. **    Become the gopher (or leave gopher status). All our routine does is force a refresh
  195. **    of the cursor.
  196. **
  197. **        fBecoming (Boolean):        TRUE if becoming gopher
  198. **
  199. **        return (Boolean):        TRUE if successful in changing status
  200. **
  201. */
  202.  
  203. Boolean CTerminalPane::BecomeGopher(Boolean fBecoming)
  204.  
  205. {
  206.     if (!fBecoming)
  207.         cursorVis = TRUE;
  208.     InvalCharRect(theColumn, theLine, theColumn, theLine);
  209.     return CPanorama::BecomeGopher(fBecoming);
  210. }
  211.  
  212.  
  213. /*______________________________________________________________________
  214. **
  215. ** SetBlinking
  216. **
  217. **    Turns on or off cursor blinking.
  218. **
  219. **        blinkMode (Boolean):        TRUE to enable cursor blinking
  220. **
  221. */
  222.  
  223. void CTerminalPane::SetBlinking(Boolean blinkMode)
  224.  
  225. {
  226.     blinkCursor = blinkMode;
  227.     if ((blinkMode)    && (gGopher == this)) {
  228.         lastCursorCol = theColumn;
  229.         lastCursorLine = theLine;
  230.         CursorMoved();
  231.     }
  232.     else {
  233.         cursorVis = TRUE;
  234.         InvalCharRect(theColumn, theLine, theColumn, theLine);
  235.     }
  236. }
  237.  
  238.  
  239. //    ムム scrolling ムム
  240.  
  241. /*______________________________________________________________________
  242. **
  243. ** ScrollToSelection
  244. **
  245. **    Ensure that the current cursor location is visible.
  246. **
  247. */
  248.  
  249. void CTerminalPane::ScrollToSelection()
  250.  
  251. {
  252.     short    hSpan, vSpan;
  253.     LongRect    topLeftRect, botRightRect;            // top left / bottom right cells of selection
  254.                                             // held over from CTable::ScrollToSelection
  255.                                             // because we might implement character selection later
  256.     LongPt    selPos;
  257.  
  258.  
  259.     // get current window parameters
  260.  
  261.     if (EmptyLongRect(&aperture))                    // nothing selected or nothing visible
  262.         return;
  263.     GetFrameSpan(&hSpan, &vSpan);
  264.     selPos = position;                            // init to current scroll position
  265.  
  266.  
  267.     // figure out where cursor (or selection) is
  268.  
  269.     CalcCharRect(theColumn, theLine, theColumn, theLine, &topLeftRect);
  270.     topLeftRect.left -= offsetX;
  271.     topLeftRect.top -= offsetY;
  272.     topLeftRect.right += offsetX;
  273.     topLeftRect.bottom += offsetY;
  274.     botRightRect = topLeftRect;
  275.             // adapt later for charcter selections
  276.  
  277.  
  278.     // calc vertical scroll
  279.  
  280.     if (topLeftRect.bottom >= position.v + vSpan)        // Is the top of selection below the bottom of frame?
  281.         selPos.v = topLeftRect.bottom - vSpan;
  282.     else if (botRightRect.top < position.v)            // Is the bottom of selection above the top of the frame?
  283.         selPos.v = botRightRect.top;
  284.  
  285.  
  286.     // calc horizontal scroll
  287.  
  288.     if (topLeftRect.right >= position.h + hSpan)        // Is the left edge of selection past the right edge of frame?
  289.         selPos.h = topLeftRect.right - hSpan;
  290.     else if (botRightRect.left < position.h)            // Is the right edge of selection before the left edge of frame?
  291.         selPos.h = botRightRect.left;
  292.  
  293.     if ((selPos.h != position.h) || (selPos.v != position.v))
  294.         ScrollTo(&selPos, TRUE);
  295.  
  296. }
  297.  
  298.  
  299. /*______________________________________________________________________
  300. **
  301. ** DisableKeyScroll
  302. **
  303. **    Turn on or off keyboard scrolling commands.
  304. **
  305. **        disable (Boolean):    TRUE to turn off keyboard scrolling
  306. **
  307. */
  308.  
  309. void CTerminalPane::DisableKeyScroll(Boolean disable)
  310.  
  311. {
  312.     disableKeyScroll = disable;
  313. }
  314.  
  315.  
  316. /*______________________________________________________________________
  317. **
  318. ** DoKeyDown
  319. **
  320. **    Override to enable or disable key scrolling (which is implemented in CPanorama).
  321. **
  322. */
  323.  
  324. void CTerminalPane::DoKeyDown(char theChar, Byte keyCode, EventRecord* macEvent)
  325.  
  326. {
  327.     if (disableKeyScroll)
  328.         CBureaucrat::DoKeyDown(theChar, keyCode, macEvent);
  329.     else
  330.         CPanorama::DoKeyDown(theChar, keyCode, macEvent);
  331. }
  332.  
  333.  
  334. //    ムム terminal emulation methods ムム
  335.  
  336. /*______________________________________________________________________
  337. **
  338. ** DoClearScreen
  339. **
  340. **    Clear the screen and move the cursor to (0,0).
  341. **
  342. */
  343.  
  344. void CTerminalPane::DoClearScreen()
  345.  
  346. {
  347.     register short x, y;
  348.     
  349.     theLine = theColumn = 0;
  350.     CursorMoved();
  351.  
  352.     for (y = 0; y < maxY; ++y)
  353.         for (x = 0; x < maxX; ++x)
  354.             theScreen[y][x] = ' ';
  355.     Refresh();
  356. }
  357.  
  358.  
  359. /*______________________________________________________________________
  360. **
  361. ** DoWriteChar
  362. **
  363. **    Write a character to the terminal. This method handles *basic* terminal emulation.
  364. **    To provide more sophisticated emulation, override this method.
  365. **
  366. **        theChar (char):        the character to write
  367. **
  368. */
  369.  
  370. void CTerminalPane::DoWriteChar(char theChar)
  371.  
  372. {
  373.  
  374.     // parse a few control characters
  375.  
  376.     switch (theChar) {
  377.  
  378.         case charNUL:
  379.             break;
  380.  
  381.         case charBEL:
  382.             SysBeep(0);
  383.             break;
  384.  
  385.         case charBS:
  386.             if (theColumn > 0)
  387.                 theColumn--;
  388.             CursorMoved();
  389.             break;
  390.  
  391.         case charHT:
  392.             theColumn = ((short) ((theColumn + 7) / 8)) * 8;
  393.             if (theColumn >= maxX)
  394.                 theColumn = maxX-1;
  395.             CursorMoved();
  396.             break;
  397.             
  398.         case charLF:
  399.             if (theLine < maxY-1)
  400.                 theLine++;
  401.             else
  402.                 ScrollTerm();
  403.             CursorMoved();
  404.             ScrollToSelection();
  405.             break;
  406.             
  407.         case charFF:
  408.             DoClearScreen();
  409.             ScrollToSelection();
  410.             break;
  411.             
  412.         case charCR:
  413.             theColumn = 0;
  414.             CursorMoved();
  415.             break;
  416.         
  417.         default:
  418.             theScreen[theLine][theColumn] = theChar;
  419.             InvalCharRect(theColumn, theLine, theColumn, theLine);
  420.             if (theColumn < maxX-1)
  421.                 theColumn++;
  422.             CursorMoved();
  423.     }
  424. }
  425.  
  426.  
  427. /*______________________________________________________________________
  428. **
  429. ** DoWriteStr
  430. **
  431. **    Write a string to the terminal. This method is optimized to handle text strings. It skips
  432. **    any control characters and sends them directly to DoWriteChar.
  433. **
  434. **        theStr (char*):        the string to write (C string)
  435. **
  436. */
  437.  
  438. void CTerminalPane::DoWriteStr(char* theStr)
  439.  
  440. {
  441.     short leftCol;
  442.  
  443.     // optimize for text characters
  444.     
  445.     while (*theStr) {
  446.         if (*theStr >= ' ') {
  447.             leftCol = theColumn;
  448.             while (*theStr >= ' ') {
  449.                 theScreen[theLine][theColumn] = *(theStr++);
  450.                 if (theColumn < maxX-1)
  451.                     theColumn++;
  452.             }
  453.             InvalCharRect(leftCol, theLine, theColumn, theLine);
  454.             CursorMoved();
  455.         }
  456.         if (*theStr)
  457.             DoWriteChar(*(theStr++));
  458.     }
  459. }
  460.  
  461.  
  462. /*______________________________________________________________________
  463. **
  464. ** DoWriteBfr
  465. **
  466. **    Write the contents of a text buffer to the terminal. This method
  467. **    merely dishes out the characters to the DoWriteChar method.
  468. **
  469. **        theStr (char*):        the buffer to write
  470. **        theSize (short):    size of the data buffer
  471. **
  472. */
  473.  
  474. void CTerminalPane::DoWriteBfr(char* theStr, short theSize)
  475.  
  476. {
  477.     while (theSize--)
  478.         DoWriteChar(*(theStr++));
  479. }
  480.  
  481.  
  482. /*______________________________________________________________________
  483. **
  484. ** DoWriteCharNum
  485. **
  486. **    Write a character number to the terminal. Provided as a debugging routine
  487. **    by other classes. The number is bracketed by the two characters indicated, i.e.
  488. **    if you call ::DoWriteCharNum('!', '[', ']'), you get [33] written to the terminal.
  489. **
  490. **        theChar (char):        the character number to write
  491. **        leftBracket (char):    prefix to character number
  492. **        rightBracket (char):    suffix to character number
  493. **
  494. */
  495.  
  496. void CTerminalPane::DoWriteCharNum(char theChar, char leftBracket, char rightBracket)
  497.  
  498. {
  499.     Str255 cNumber;
  500.  
  501.     if (leftBracket)
  502.         DoWriteChar(leftBracket);
  503.  
  504.     NumToString((short) theChar, cNumber);
  505.     cNumber[cNumber[0]+1] = '¥0';
  506.     DoWriteStr((char*) (&cNumber)+1);
  507.  
  508.     if (rightBracket)    
  509.         DoWriteChar(rightBracket);
  510. }
  511.  
  512.  
  513. /*______________________________________________________________________
  514. **
  515. ** DoEraseChar
  516. **
  517. **    Erase one character from screen (backspace).
  518. **
  519. */
  520.  
  521. void CTerminalPane::DoEraseChar()
  522.  
  523. {
  524.     register short x;
  525.     
  526.     if (theColumn > 0) {
  527.         theColumn--;
  528.         for (x = theColumn; x < maxX-1; x++)
  529.             theScreen[theLine][x] = theScreen[theLine][x+1];
  530.         theScreen[theLine][maxX-1] = ' ';
  531.         InvalCharRect(theColumn, theLine, maxX-1, theLine);
  532.         CursorMoved();
  533.     }
  534. }
  535.  
  536.  
  537. /*______________________________________________________________________
  538. **
  539. ** DoEraseLine
  540. **
  541. **    Move the cursor back to beginning of line & erase line.
  542. **
  543. */
  544.  
  545. void CTerminalPane::DoEraseLine()
  546.  
  547. {
  548.     theColumn = 0;
  549.     ClearToEOL(0, theLine);
  550.     CursorMoved();
  551. }
  552.  
  553.  
  554. //    ムム private screen handling methods ムム
  555.  
  556. /*______________________________________________________________________
  557. **
  558. ** ClearToEOL (protected method)
  559. **
  560. **    Clear from the indicated point to the end of a line. Upper left
  561. **    corner is (0,0).
  562. **
  563. **        col (short):    first column in line to clear
  564. **        line (short):    line to be cleared
  565. **
  566. */
  567.  
  568. void CTerminalPane::ClearToEOL(short col, short line)
  569.  
  570. {
  571.     InvalCharRect(col, line, maxX-1, line);
  572.     while (col < maxX)
  573.         theScreen[line][col++] = ' ';
  574. }
  575.  
  576.  
  577. /*______________________________________________________________________
  578. **
  579. ** ClearToEOS (protected method)
  580. **
  581. **    Clear from the indicated point to the end of the screen. Upper left
  582. **    corner is (0,0).
  583. **
  584. **        col (short):    first column in first line to clear
  585. **        line (short):    first line to be cleared
  586. **
  587. */
  588.  
  589. void CTerminalPane::ClearToEOS(short col, short line)
  590.  
  591. {
  592.     while (line < maxY) {
  593.         ClearToEOL(col, line++);
  594.         col = 0;
  595.     }
  596. }
  597.  
  598.  
  599. /*______________________________________________________________________
  600. **
  601. ** ScrollTerm
  602. **
  603. **    Push everything on screen up one line.
  604. **
  605. */
  606.  
  607. void CTerminalPane::ScrollTerm()
  608.  
  609. {
  610.     BlockMove(&theScreen[1][0], &theScreen[0][0], (maxY-1) * maxX);
  611.     ClearToEOL(0, maxY-1);
  612.     Refresh();
  613. }
  614.  
  615.  
  616. /*______________________________________________________________________
  617. **
  618. ** InvalCharRect (protected method)
  619. **
  620. **    Invalidate a section of the pane based on the character coordinates
  621. **    provided. Upper left corner is (0,0).
  622. **
  623. **        left (short):        left edge of character rectangle
  624. **        top (short):        top edge
  625. **        right (short):        right edge, inclusive
  626. **        bottom (short):        bottom edge, inclusive
  627. **
  628. */
  629.  
  630. void CTerminalPane::InvalCharRect(short left, short top, short right, short bottom)
  631.  
  632. {
  633.     LongRect    theLongRect;
  634.  
  635.     CalcCharRect(left, top, right, bottom, &theLongRect);
  636.     Prepare();
  637.     RefreshLongRect(&theLongRect);
  638. }
  639.  
  640.  
  641. /*______________________________________________________________________
  642. **
  643. ** CursorMoved
  644. **
  645. **    Update the blinking cursor block.
  646. **
  647. */
  648.  
  649. void CTerminalPane::CursorMoved()
  650.  
  651. {
  652.     cursorVis = TRUE;
  653.     lastCursorTick = LMGetTicks();
  654.     if (lastCursorLine == theLine) {
  655.         switch (charsToInvalLine) {
  656.             case 0:                            // optimization to reduce calls to InvalRect()
  657.                 break;
  658.             case 1:
  659.                 InvalCharRect(0, theLine, maxX-1, theLine);
  660.                 charsToInvalLine = 0;
  661.                 break;
  662.             default:
  663.                 InvalCharRect(lastCursorCol, lastCursorLine, lastCursorCol, lastCursorLine);
  664.                 InvalCharRect(theColumn, theLine, theColumn, theLine);
  665.                 charsToInvalLine--;
  666.         }
  667.     }
  668.     else {
  669.         InvalCharRect(lastCursorCol, lastCursorLine, lastCursorCol, lastCursorLine);
  670.         InvalCharRect(theColumn, theLine, theColumn, theLine);
  671.         charsToInvalLine = resetInvalsChar;
  672.     }
  673.     lastCursorCol = theColumn;
  674.     lastCursorLine = theLine;
  675. }
  676.  
  677.  
  678. /*______________________________________________________________________
  679. **
  680. ** CalcCharRect (protected method)
  681. **
  682. **    Calculate the screen coordinates for a specified rectangle of
  683. **    character coordinates. Upper left corner is (0,0).
  684. **
  685. **        left (short):            left edge of char rectangle
  686. **        top (short):            top edge
  687. **        right (short):            right edge, inclusize
  688. **        bottom (short):            bottom edge, inclusive
  689. **        theRect (LongRect*):    coordinates returned to this rectangle
  690. **
  691. */
  692.  
  693. void CTerminalPane::CalcCharRect(short left, short top, short right, short bottom,
  694.                             LongRect* theRect)
  695.  
  696. {
  697.     SetLongRect(theRect,
  698.                 (long) left * pixelsX + offsetX,
  699.                 (long) top * pixelsY + offsetY,
  700.                 (long) (right+1) * pixelsX + offsetX,
  701.                 (long) (bottom+1) * pixelsY + offsetY);
  702. }
  703.  
  704.  
  705. /*______________________________________________________________________
  706. **
  707. ** InvertCursor
  708. **
  709. **    Invert a single character.
  710. **
  711. **        col (short):    the column number
  712. **        line (short):    the line number
  713. **
  714. */
  715.  
  716. void CTerminalPane::InvertCursor(short col, short line)
  717.  
  718. {
  719.     LongRect    theLongRect;
  720.     Rect        theRect;
  721.     
  722.     CalcCharRect(col, line, col, line, &theLongRect);
  723.     LongToQDRect(&theLongRect, &theRect);
  724.     InvertRect(&theRect);
  725.     if (gGopher != this) {
  726.         InsetRect(&theRect, 1, 1);
  727.         InvertRect(&theRect);
  728.     }
  729. }
  730. #endif